import os
import sys

import validators
import yaml

import ci_api
import sort_util
import json


def check_url():
    global ci_url
    if not validators.url(ci_url):
        print('error: ci_url格式校验错误，不是一个正确的URL地址', flush = True)
        sys.exit(1)
    if ci_url.endswith("/"):
        ci_url = ci_url[0:len(ci_url) - 1]


ci_url = os.getenv('JIANMU_CI_URL')
check_url()
group_file_path = os.getenv('JIANMU_GROUP_FILE_PATH')
git_path = os.getenv('JIANMU_GIT_PATH')
deletable = os.getenv('JIANMU_DELETABLE')
sortable = os.getenv('JIANMU_SORTABLE')
succeed_number = 0
failed_number = 0

if sortable == 'true':
    print('warning: 排序进行中，为避免排序错误，请不要手动新增、修改、删除项目/项目组数据', flush = True)
    print(flush = True)


def read_project_group_yaml(path):
    if not path.startswith("/"):
        path = "/" + path
    try:
        fr = open(git_path + path, 'r', encoding="utf-8")
        yml_dict = yaml.full_load(fr)
    except Exception as e:
        print("error: 解析 yml 文件失败，", e, flush = True)
        sys.exit(1)
    return yml_dict


def read_project_yaml(path):
    if not path.startswith("/"):
        path = "/" + path
    try:
        fr = open(git_path + path, 'r', encoding="utf-8")
        yml_dict = yaml.full_load(fr)
    except Exception as e:
        print("error: 解析 yml 文件失败，", e, flush = True)
        return None
    return yml_dict


def check_projects(projects_dict):
    if not projects_dict.get('groups'):
        print('error: 配置文件中 groups 未定义', flush = True)
        sys.exit(1)
    names = []
    for p in projects_dict.get('groups'):
        name = p.get('name')
        if name in names:
            print('error: 配置文件中 name 定义重复', flush = True)
            sys.exit(1)
        names.append(name)
        if not p.get('projects'):
            print('error: 配置文件中 projects 未定义', flush = True)
            sys.exit(1)


def import_project():
    projects_dict = read_project_group_yaml(group_file_path)
    check_projects(projects_dict)
    ci_api.get_token(ci_url)
    ci_groups = ci_api.get_project_groups(ci_url)
    ci_projects = get_all_projects(ci_groups)
    groups = create_project_group(projects_dict['groups'], ci_groups)

    for group in groups:
        if not group.get('id'):
            continue
        print('开始导入：', group['name'], '分组', flush = True)
        import_groups(group['projects'], group['id'], group['name'], ci_projects)
        print(flush = True)
    delete_project(ci_projects)


# 查询所有项目
def get_all_projects(ci_groups):
    ci_projects = []
    for group in ci_groups:
        ci_projects.extend(get_group_projects(group['id'], group['name']))
    return ci_projects


# 查询项目组项目
def get_group_projects(group_id, group_name):
    ci_projects = []
    page = ci_api.get_projects(ci_url, 1, group_id)
    for ci_project in page['list']:
        ci_project['projectGroupId'] = group_id
        ci_project['projectGroupName'] = group_name
    ci_projects.extend(page['list'])
    for index in range(1, page['pages'] + 1):
        projects = ci_api.get_projects(ci_url, index + 1, group_id).get('list')
        for ci_project in projects:
            ci_project['projectGroupId'] = group_id
            ci_project['projectGroupName'] = group_name
        ci_projects.extend(projects)
    return ci_projects


# 创建项目组
def create_project_group(groups, ci_groups):
    group_names = [group['name'] for group in groups if group['name']]
    ci_group_names = [ci_group['name'] for ci_group in ci_groups]
    new_groups = set(group_names) - set(ci_group_names)
    for name in new_groups:
        ci_api.create_project_group(ci_url, name)
    if new_groups:
        ci_groups = ci_api.get_project_groups(ci_url)
        print(flush = True)

    # 赋值项目组ID
    for group in groups:
        if not group['name']:
            group['name'] = '默认分组'
        for ci_group in ci_groups:
            if group['name'] == ci_group['name']:
                group['id'] = ci_group['id']
    # 项目组排序
    if sortable == 'true':
        sort_util.sort_group(groups, ci_groups, ci_url)
    return groups


def import_groups(projects, group_id, group_name, ci_projects):
    global failed_number, succeed_number
    dsl_projects = []
    for project_path in projects:
        project_dict = read_project_yaml(project_path)
        if not project_dict:
            failed_number = failed_number + 1
            continue
        name = get_project_name(project_dict, project_path)
        if not name:
            print('error: 导入项目文件\"' + project_path + '\"中未定义name', flush = True)
            failed_number = failed_number + 1
            continue
        # 将项目添加到dsl_projects中
        project = {
            'id': None,
            'name': name
        }
        ci_project = match_project_name(name, ci_projects)
        # 读取项目dsl文件
        project_path = project_path if project_path.startswith('/') else '/' + project_path
        dsl_text = open(git_path + project_path).read()
        if ci_project:
            dsl_projects.append(project)
            # 添加到项目组
            if ci_project['projectGroupId'] != group_id:
                ci_api.add_project(ci_url, group_id, ci_project['id'], ci_project['projectGroupName'],
                                   group_name, name, project_path)
            is_diff = compare_project(ci_project, name, project_path, dsl_text)
            if is_diff:
                succeed_number = succeed_number + 1
                continue
            flag = ci_api.update_project(ci_url, group_id, name, ci_project.get('id'), project_path, dsl_text)
            if flag:
                succeed_number =  succeed_number + 1
            else:
                failed_number = failed_number + 1
        else:
            is_created = ci_api.create_project(ci_url, group_id, name, project_path, dsl_text)
            if is_created:
                dsl_projects.append(project)
                succeed_number = succeed_number + 1
            else:
                failed_number = failed_number + 1
    # 项目排序
    if sortable == 'true':
        projects = get_group_projects(group_id, group_name)
        sort_util.sort_project(dsl_projects, projects, ci_url, group_id)


def compare_project(ci_project, name, project_path, dsl_text):
    ci_dsl_text = ci_api.get_project_detail(ci_url, ci_project.get('id')).get('dslText')
    if dsl_text == ci_dsl_text:
        print('success:', name + '；', project_path + '；', '项目dsl内容相同，无需更新', flush = True)
        return True
    else:
        return False


# 获取项目dsl文件中的项目名称
def get_project_name(project_dict, project_path):
    if project_dict.get('name'):
        return project_dict['name']
    elif project_dict.get('pipeline'):
        print('warn:', project_path + '；',
              'v2.0.0-beta.2 开始不支持"name"定义在"workflow"或"pipeline"段落下', flush = True)
        return project_dict['pipeline'].get('name')
    elif project_dict.get('workflow'):
        print(
            'warn:', project_path + '；',
            'v2.0.0-beta.2 开始不支持"name"定义在"workflow"或"pipeline"段落下', flush = True)
        return project_dict['workflow'].get('name')
    else:
        return None


def match_project_name(name, projects):
    for p in projects:
        if 'LOCAL' == p.get('source') and name == p.get('name'):
            p['exist'] = True
            return p


# 删除不存在的项目
def delete_project(projects):
    if 'false' == deletable:
        return
    print('开始删除项目：', flush = True)
    for p in projects:
        if 'LOCAL' == p.get('source') and not p.get('exist'):
            ci_api.delete_project(ci_url, p.get('id'), p.get('name'))


import_project()
result_file = {
    'succeed_number': succeed_number,
    'failed_number': failed_number
}
json = json.dumps(result_file, ensure_ascii=False, indent=4)
with open('/usr/result_file', 'w') as f:
    f.write(json)
print('输出参数：', flush = True)
print(json, flush = True)
